﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Kinect;

namespace KinectPowerPointControl_sample1_Fukidashi
{
    static class ProcessCallForApplauseGesture
    {
        private static long lastActivated = 0; //最後にこのジェスチャーが発生したタイミング（100ナノ秒単位のtickで保持）
        private static long SLEEP_TIME = 5 * 1000 * 1000 * 10; //発動後、発動を抑える時間

        public static bool callForApplauseState(LinkedList<SkeletonLog> skeletonLogs)
        {
            if (DateTime.Now.Ticks - lastActivated > SLEEP_TIME) { lastActivated = 0; } //発動後、発動を抑える時間が経過した場合
            if (skeletonLogs.Count < 6 ||   //直近1.5秒の断面が存在しない場合
                lastActivated > 0)          //発動後、発動を抑える時間が経過した場合
            {
                return false; 
            }

            LinkedList<SkeletonLog>.Enumerator e = skeletonLogs.GetEnumerator();

            //以下の全てを満たすかどうか
            //①直近の0.6秒間、以下の状態が維持されている
            //　・Spine（背骨）とElbow（肘）のX距離が15cm以上空いている
            //　・Elbow（肘）とWrist（手首）のX距離が15cm以上空いている
            //　・Elbow（肘）が、Shoulder（肩）より下にある。
            //②直近の1.5秒で、Spine（背骨）が左右に15cm以上移動していない。

            float spine_x_min = 0, spine_x_max = 0;

            for (int i = 0; i < 6; i++)
            {
                if (!e.MoveNext()) { return false; }

                if (i < 3 && !checkHands((JointCollectionEquivalent)(e.Current.joints))) //0.6秒以内の断面についてのチェック
                {
                    return false;
                }
                
                if (i == 0){ //直近断面用の②チェック用設定
                    spine_x_min = e.Current.joints[JointType.Spine].Position.X;
                    spine_x_max = spine_x_min;
                } else { //直近断面以外用の②チェック処理
                    spine_x_max = e.Current.joints[JointType.Spine].Position.X > spine_x_max ?
                        e.Current.joints[JointType.Spine].Position.X : spine_x_max;
                    spine_x_min = e.Current.joints[JointType.Spine].Position.X > spine_x_min ?
                        e.Current.joints[JointType.Spine].Position.X : spine_x_min;
                    if (spine_x_max - spine_x_min > 0.15) { return false; }
                }
            }

            lastActivated = DateTime.Now.Ticks;
            return true;
        }

        private static bool checkHands(JointCollectionEquivalent joints){

            Joint spine = joints[JointType.Spine];
            Joint elbow_l = joints[JointType.ElbowLeft];
            Joint wrist_l = joints[JointType.WristLeft];
            Joint elbow_r = joints[JointType.ElbowRight];
            Joint wrist_r = joints[JointType.WristRight];
            Joint shoulder = joints[JointType.ShoulderCenter];

            return (System.Math.Abs(spine.Position.X - elbow_r.Position.X) >= 0.15 &&
                    System.Math.Abs(spine.Position.X - elbow_l.Position.X) >= 0.15 &&
                    System.Math.Abs(elbow_l.Position.X - wrist_l.Position.X) >= 0.15 &&
                    System.Math.Abs(elbow_r.Position.X - wrist_r.Position.X) >= 0.15 &&
                    elbow_l.Position.Y < shoulder.Position.Y /* && elbow_l.Position.Y < wrist_l.Position.Y*/ &&
                    elbow_r.Position.Y < shoulder.Position.Y /* && elbow_r.Position.Y < wrist_r.Position.Y*/ );
        }
    }

}
